﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WSAP;

namespace CouplingBeamStiff
{
    class Structure
    {
        /// <summary>
        /// 楼层集合
        /// </summary>
        private List<ComponentBasic> StoreyList { get; set; }
        /// <summary>
        /// 全楼节点集合
        /// </summary>
        private List<Node> NodeList { get; set; }
        /// <summary>
        /// 有限元模型
        /// </summary>
        private WModelNet Model { get; set; }
        /// <summary>
        /// 结构高度
        /// </summary>
        public double StrucHeight 
        {
            get
            {
                return (from node in this.NodeList select node.Y).ToList().Max();
            }
        }
        /// <summary>
        /// 获得最小层高
        /// </summary>
        /// <returns></returns>
        public double MinStoryHeight
        {
            get
            {
                return (from story in this.StoreyList select story.GetStoryHeight()).ToList().Min();
            }
        }
        /// <summary>
        /// 获得最大层高
        /// </summary>
        /// <returns></returns>
        public double MaxStoryHeight
        {
            get
            {
                return (from story in this.StoreyList select story.GetStoryHeight()).ToList().Max();
            }
        }
        public double MinBeamHeight 
        {
            get
            {
                return (from story in this.StoreyList select story.GetBeamHeight()).ToList().Min();
            }
        }

        /// <summary>
        /// 添加连肢剪力墙(中梁为壳单元)组件
        /// </summary>
        /// <param name="leftWallWidth"></param>
        /// <param name="storyHeight"></param>
        /// <param name="middleBeamWidth"></param>
        /// <param name="middleBeamHeight"></param>
        /// <param name="rightWallWidth"></param>
        public void AddCoupledShearWall(double leftWallWidth,double storyHeight,double middleBeamWidth,double middleBeamHeight,
            double rightWallWidth)
        {
            this.StoreyList.Add(new CoupledShearWall(this.StoreyList.Count + 1, leftWallWidth, rightWallWidth, storyHeight, middleBeamWidth, middleBeamHeight));
        }
        /// <summary>
        /// 添加连肢剪力墙(中梁为梁单元)组件
        /// </summary>
        /// <param name="leftWallWidth"></param>
        /// <param name="storyHeight"></param>
        /// <param name="middleBeamWidth"></param>
        /// <param name="middleBeamHeight"></param>
        /// <param name="rightWallWidth"></param>
        public void AddNewCoupledShearWall(double leftWallWidth, double storyHeight, double middleBeamWidth, double middleBeamHeight,
            double rightWallWidth)
        {
            this.StoreyList.Add(new NewCoupledShearWall(this.StoreyList.Count + 1, leftWallWidth, rightWallWidth, storyHeight, middleBeamWidth, middleBeamHeight));
        }
        public void Mesh()
        {
            double Yoffset = 0;
            foreach(var story in this.StoreyList)
            {
                story.Mesh(Yoffset);
                Yoffset += story.GetStoryHeight();
            }
            this.NodeFilter();
        }
        public void NodeFilter()
        {
            List<Node> OriginNodeList = new List<Node>();
            this.NodeList = new List<Node>();
            //提取全部楼层的节点
            this.StoreyList.ForEach(Storey => OriginNodeList.AddRange(Storey.GetNodeList()));
            //初始化字典
            var dict = new Dictionary<double, Dictionary<double, Node>>();
            //函数指针是否存在相同节点
            Func<Node, bool> isSameNodeExist = (node) =>
            {
                //是否存在
                if (!dict.ContainsKey(node.X))
                {
                    dict.Add(node.X, new Dictionary<double, Node> { { node.Y, node } });
                    return false;
                }
                else if (!dict[node.X].ContainsKey(node.Y))
                {
                    dict[node.X].Add(node.Y, node);
                    return false;
                }
                else node.Index = dict[node.X][node.Y].Index;
                return true;
            };
            //过滤相同节点
            foreach (var originnode in OriginNodeList)
            {
                //节点已存在
                if (isSameNodeExist(originnode))
                    continue;
                //赋予编号
                originnode.Index = this.NodeList.Count + 1;
                this.NodeList.Add(originnode);
            }
        }
        /// <summary>
        /// 建立有限元模型
        /// </summary>
        public bool SetWModelNet()
        {
            this.Mesh();
            //实例化
            this.Model = new WModelNet();
            //添加节点
            this.NodeList.ForEach(node => Model.AddNode(node.Index, node.X, 0.0, node.Y));
            //获取系列加载点
            //var loadNodeList = this.GetLoadNodeList();
            //荷载系数
            var loadFactor = GlobalVar.MaxLoad / this.StrucHeight;
            //遍历加载点获得各个点加载力
            this.StoreyList.ForEach(Storey => Storey.AddNodeLoad(this.Model, this.NodeList, loadFactor));
            //loadNodeList.ForEach(loadnode => Model.AddNodeLoad(loadnode.Index, 1, loadnode.Y / MaxY * MaxLoad));
            //loadNodeList.ForEach(loadnode => Model.AddNodeLoad(loadnode.Index, 1, MaxLoad));
            //添加单元
            foreach (var storey in this.StoreyList)
            {
                if (!storey.AddElements(Model)) return false;
            }
            //约束Z坐标为0的点
            this.Model.FixZ(0.0);
            return true;
        }

        /// <summary>
        /// 有限元求解分析
        /// </summary>
        public bool Analysis()
        {
            //创建有限元模型
            if (!this.Model.CreateFEModel(false)) return this.Model.ShowWarningError();

            var element = this.Model.GetElements();
            //求解
            //this.Model.DoLinearStaticAnalyze();
            if (!this.Model.DoLinearStaticAnalyze()) return this.Model.ShowWarningError();
            //绘图
            this.Model.ToGraphics(new StructrueChartParam
            {
                DOF = 1,
                isNodeMaxResponseShow = true,
                ChartType = StructureChartType.GeneralStatic,
            });
            return true;
        }
        /// <summary>
        /// 获得最大响应
        /// </summary>
        /// <returns></returns>
        public double GetMaxResponse()
        {
            //创建有限元模型
            this.SetWModelNet();
            //创建有限元模型
            if (!this.Model.CreateFEModel(false)) return 0;
            //求解
            if (!this.Model.DoLinearStaticAnalyze()) return 0;
            //绘图
            this.Model.ToGraphics(new StructrueChartParam
            {
                DOF = 1,
                isNodeMaxResponseShow = true,
                ChartType = StructureChartType.GeneralStatic,
            });
            // 最大位移
            return this.Model.GetMaxNodeResponse();
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        public Structure()
        {
            this.StoreyList = new List<ComponentBasic>();
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="struc"></param>
        public Structure(Structure struc, double middleBeamHeight)
        {
            this.StoreyList = new List<ComponentBasic>();
            struc.StoreyList.ForEach(storey => this.StoreyList.Add(new CoupledShearWall(storey, middleBeamHeight)));
        }
    }
}
